package com.gzwl.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.text.DateFormat;
import java.util.*;
import java.util.regex.Matcher;

/**
 * es 同步拦截器
 *
 * 配置拦截器 @Signature
 * 前置拦截器 type = Executor.class
 * 只有写入才需要拦截 method = "update"
 * 拦截方法的参数 args = {MappedStatement.class, Object.class}
 */
@Slf4j
@Component
@Intercepts({
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class SyncEsInterceptor implements Interceptor {

    private Map<String,SynEsHandler> handlerMap = new HashMap<>();

    /**
     * 拦截器在sql执行成功后同步到es，
     * 如果同步失败抛出异常，保证数据一致性
     *
     * @param invocation
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object res = invocation.proceed();

        Object[] args = invocation.getArgs();
        if (args.length >= 2) {
            MappedStatement mappedStatement = (MappedStatement) args[0];

            //拦截到的方法，也就是注册的key
            String key = mappedStatement.getId();
            log.debug("拦截到的方法 key=",key);

            SynEsHandler synEsHandler = handlerMap.get(key);
            if(null != synEsHandler){
                try {
                    synEsHandler.handler(args[1]);
                }catch (Exception e){
                    //包装异常
                    throw new SyncEsException(e);
                }
            }else {
                log.debug("没有处理的key={}",key);
            }
        }

        return res;
    }

    @Override
    public Object plugin(Object o) {
        if(o instanceof Executor) return Plugin.wrap(o, this);
        else return o;
    }

    @Override
    public void setProperties(Properties properties) {

    }

    /**
     * 注册同步处理器
     * @param key
     * @param parameterHandler
     */
    public void regHandler(String key,SynEsHandler parameterHandler){
        handlerMap.put(key,parameterHandler);
    }
}